// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Agent.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Robotics.Runtime
{
    using System.Runtime.Serialization;

    /// <summary>
    /// A simple implementation of the IAgent contract, sufficient for registering the agent with the framework, but with no publishing or subscribing capabilities.
    /// An agent that derives from this class will need to also implement IMessagePublisher to get publishing capabilities and/or IMessageSubscriber plus IScheduledAgent for subscribing capabilities.
    /// Simple agents can derive from one of the derived classes to get these behaviors for free.
    /// </summary>
    [DataContract]
    public abstract class Agent : IAgent
    {
        /// <summary>
        /// The name of this agent instance.
        /// </summary>
        [DataMember(Name = "Name")]
        private readonly string name;

        /// <summary>
        /// The locator to use when searching for other agents.
        /// </summary>
        private AgentLocator locator;

        /// <summary>
        /// Initializes a new instance of the Agent class.
        /// Empty constructor, to allow derived classes to have one as well.
        /// </summary>
        public Agent()
        {
        }

        /// <summary>
        /// Initializes a new instance of the Agent class.
        /// This constructor is not called when the agent is created from a manifest file.
        /// </summary>
        /// <param name="name">A friendly name for this agent instance.</param>
        public Agent(string name)
        {
            this.name = name;
        }

        /// <summary>
        /// Gets the unique, friendly name of this agent instance.
        /// </summary>
        public string Name
        {
            get
            {
                return this.name;
            }
        }

        /// <summary>
        /// Gets the locator to use when searching for other agents.
        /// </summary>
        protected AgentLocator Locator
        {
            get
            {
                return this.locator;
            }
        }

        /// <summary>
        /// A method which throws ArgumentException with example in case the errorCondition is satisfied.
        /// </summary>
        /// <param name="errorCondition">The condition to be validated on the parameter</param>
        /// <param name="paramName">The parameter name to be validated</param>
        /// <param name="example">A valid example for the parameter</param>
        public static void ValidateParameter(bool errorCondition, string paramName, string example)
        {
            if (errorCondition)
            {
                throw new System.ArgumentException(string.Format("Parameter {0} is not valid. {1}", paramName, example));
            }
        }

        /// <summary>
        /// Called after construction, to allow the agent to finish initialization. 
        /// </summary>
        /// <param name="locator">A locator that can be used to find other agents.</param>
        public virtual void Initialize(AgentLocator locator)
        {
            this.locator = locator;
        }

        /// <summary>
        /// Implemented by the subclass and called when the first subscriber arrives. 
        /// This allows agents to remain idle when there are no consumers. 
        /// </summary>
        public virtual void OnActivated()
        {
        }

        /// <summary>
        /// Implemented by the subclass and called when the last subscriber leaves. Agents will
        /// typically use this call to reduce their CPU utilization when there are no subscribers.
        /// </summary>
        public virtual void OnDeactivated()
        {
        }
    }
}
